package com.kidback.bbloc259.base.lang;

import com.kidback.bbloc259.base.AbsObserver;

import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class Delay {

    public static void fromIterable(List<Long> intervalList, AbsObserver<Long> observer) {
        Observable.fromIterable(intervalList)
                .observeOn(AndroidSchedulers.mainThread())
                .concatMap(new Function<Long, ObservableSource<Long>>() {
                    @Override
                    public ObservableSource<Long> apply(Long longParam) throws Exception {
                        return Observable.timer(longParam, TimeUnit.MILLISECONDS)
                                .map(new Function<Long, Long>() {
                                    @Override
                                    public Long apply(Long aLong) throws Exception {
                                        return longParam;
                                    }
                                });
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    public static void interval(long period, Observer<Long> observer) {
        Observable.interval(0, period, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    public static void intervalCount(int count, long period, Observer<Long> observer) {
        Observable.intervalRange(0, count, 0, period, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    public static void interval(long initialDelay, long period, Observer<Long> observer) {
        Observable.interval(initialDelay, period, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer);
    }

    public static void interval(long initialDelay, long period,
                                Runnable1<Long> nextRunnable, Runnable1<Long> completeRunnable) {
        Observable.interval(initialDelay, period, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Long aLong) {
                        if (nextRunnable != null) {
                            nextRunnable.run(aLong);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        if (completeRunnable != null) {
                            completeRunnable.run(null);
                        }
                    }
                });
    }

    public static void interval(int start, int count, long initialDelay, long period, Runnable1<Long> nextRunnable) {
        interval(start, count, initialDelay, period, nextRunnable, null);
    }

    public static void interval(int start, int count, long initialDelay, long period,
                                Runnable1<Long> nextRunnable, Runnable1<Long> completeRunnable) {
        interval(start, count, initialDelay, period, nextRunnable, completeRunnable, null);
    }

    public static void interval(int start, int count, long initialDelay, long period,
                                Runnable1<Long> nextRunnable, Runnable1<Long> completeRunnable,
                                Runnable1<Disposable> disposableRunnable1) {
        Observable.intervalRange(start, count, initialDelay, period, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        if (disposableRunnable1 != null) {
                            disposableRunnable1.run(d);
                        }
                    }

                    @Override
                    public void onNext(Long aLong) {
                        if (nextRunnable != null) {
                            nextRunnable.run(aLong);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        if (completeRunnable != null) {
                            completeRunnable.run(null);
                        }
                    }
                });
    }

    public static Disposable delay(long delay, Runnable0 runnable) {
        return Observable.timer(delay, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        runnable.run();
                    }
                });
    }

    public static Disposable delay(long delay, TimeUnit timeUnit, Runnable1 runnable) {
        return Observable.timer(delay, timeUnit)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        runnable.run(null);
                    }
                });
    }

    public static Disposable delay(long delay, TimeUnit timeUnit, Consumer<Long> consumer) {
        return Observable.timer(delay, timeUnit)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);
    }

    public static void delayRepeat(List<Long> intervalList, Runnable1 nextRunnable, Runnable1 completeRunnable) {
        Observable.fromIterable(intervalList)
                .concatMap(new Function<Long, ObservableSource<Long>>() {
                    @Override
                    public ObservableSource<Long> apply(Long aLong) throws Exception {
                        return Observable.timer(aLong, TimeUnit.MILLISECONDS);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Long aLong) {
                        if (nextRunnable != null) {
                            nextRunnable.run(aLong);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        if (completeRunnable != null) {
                            completeRunnable.run(null);
                        }
                    }
                });
    }

}
